package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"
)

func main() {
	var port string
	flag.StringVar(&port, //第一个参数：存放值的参数地址
		"port",    //第二个参数：命令行参数的名称
		"60011",   //第三个参数：命令行不输入时的默认值
		"软件监听的端口") //第四个参数：该参数的描述信息，help命令时会显示
	var target string
	flag.StringVar(&target, //第一个参数：存放值的参数地址
		"add",                 //第二个参数：命令行参数的名称
		"mc.hypixel.io:25565", //第三个参数：命令行不输入时的默认值
		"转发到的地址")              //第四个参数：该参数的描述信息，help命令时会显示
	var strms string
	flag.StringVar(&strms, //第一个参数：存放值的参数地址
		"ms",               //第二个参数：命令行参数的名称
		"false",            //第三个参数：命令行不输入时的默认值
		"增加的延迟,关闭请填入false") //第四个参数：该参数的描述信息，help命令时会显示
	var fkh string
	flag.StringVar(&fkh, //第一个参数：存放值的参数地址
		"fuck",  //第二个参数：命令行参数的名称
		"false", //第三个参数：命令行不输入时的默认值
		"fuckhypixel-骗过hypixel的域名验证,做hypixel的加速ip必须启用.默认关闭,关闭请填入false,请填入您做加速域名的长度(完整,不是主域名),长度必须大于等于14") //第四个参数：该参数的描述信息，help命令时会显示
	var hwl string
	flag.StringVar(&hwl, //第一个参数：存放值的参数地址
		"hwl",             //第二个参数：命令行参数的名称
		"false",           //第三个参数：命令行不输入时的默认值
		"域名白名单功能,false禁用") //第四个参数：该参数的描述信息，help命令时会显示
	var apis string
	flag.StringVar(&apis, //第一个参数：存放值的参数地址
		"api",   //第二个参数：命令行参数的名称
		"false", //第三个参数：命令行不输入时的默认值
		"域名白名单api功能,false禁用,不禁用请输入对接api端口") //第四个参数：该参数的描述信息，help命令时会显示
	flag.Parse()
	var ms int
	if strms != "false" {
		ms, _ = strconv.Atoi(strms)
	} else {
		ms = -1
	}
	fmt.Println("监听的端口:", port, ",转发到地址:", target, ",假延迟(-1为不造假):", ms, ",绕域名验证(除false都是开启,如果还是用不了可能是你长度填的有问题)", fkh)
	go api(apis) //api接口
	listen, err := net.Listen("tcp", "0.0.0.0:"+port)
	if err != nil {
		fmt.Println("err1:", err)
		return
	}
	for {
		clconn, err := listen.Accept()
		if err != nil {
			fmt.Println("err2:", err)
			continue
		}
		//target := "120.132.110.191:10001"
		raddr, err := net.ResolveTCPAddr("tcp", target)
		if err != nil {
			fmt.Println("err:", err)
			continue
		}
		// Establish a connection with the server.
		seconn, err := net.DialTCP("tcp", nil, raddr)
		if err != nil {
			fmt.Println("err2:", err)
			continue
		}

		// 关闭nodelay
		seconn.SetNoDelay(false)
		//seconn, err := net.Dial("tcp", "160.116.119.210:60001")
		go client(seconn, clconn, ms, fkh, hwl)
		go sever(seconn, clconn)
		//go process(clconn)
	}
}

func client(seconn net.Conn, clconn net.Conn, ms int, fkh string, hwl string) {
	defer seconn.Close()
	defer clconn.Close()
	m := false
	num := 0
	if ms == -1 {
		m = true
	}
	h := false
	if fkh == "false" {
		h = true
	}
	for {
		reader := bufio.NewReader(clconn)
		d := false
		if num > 8 {
			num = -1
		} else if num <= -1 {
			d = true
			m = true
			h = true
		} else {
			num++
		}
		var buf [16384]byte
		n, err := reader.Read(buf[:])
		if err != nil {
			fmt.Println("err7:", err)
			break
		}
		data := string(buf[:n])
		if m == false {
			if strings.Index(data, "\x09\x01") == 0 {
				time.Sleep(time.Duration(ms) * time.Millisecond)
				_, err = clconn.Write(buf[:n])
				if err != nil {
					fmt.Println("err7:", err)
					break
				}
				m = true
			} else {
				if strings.Index(data, "\x00\x04") == 1 {
					m = true
				}
				d = true
			}
		} else {
			d = true
		}
		n1, _ := strconv.Atoi(fkh)
		if h == false && n > n1+4 {
			d = false
			if strings.Contains(data, "\x00\x2f") {
				if hwl != "false" {
					host := data[4 : 4+n1]
					fmt.Println(host)
					_, err := os.Stat("sips_data/" + host)
					if err != nil {
						seconn.Close()
						clconn.Close()
						return
					} else {
						bytes, err := ioutil.ReadFile("sips_data/" + host)
						if err != nil {
							fmt.Println(err)
							return
						}
						iptime, _ := strconv.Atoi(string(bytes[:10]))
						if iptime > (int)(time.Now().Unix()) {
							_, err = seconn.Write(buf[:4])
							if err != nil {
								fmt.Println("err7:", err)
								break
							}
							for i := 2; i < 2+n1-12; i++ {
								_, err = seconn.Write([]byte("a"))
								if err != nil {
									fmt.Println("err7:", err)
									break
								}
							}
							_, err = seconn.Write([]byte(".hypixel.net"))
							if err != nil {
								fmt.Println("err7:", err)
								break
							}
							_, err = seconn.Write(buf[n1+4 : n])
							if err != nil {
								fmt.Println("err7:", err)
								break
							}
							fmt.Println(data)
							h = true
						} else {
							seconn.Close()
							clconn.Close()
							return
						}
					}
				} else {
					_, err = seconn.Write(buf[:4])
					if err != nil {
						fmt.Println("err7:", err)
						break
					}
					for i := 2; i < 2+n1-12; i++ {
						_, err = seconn.Write([]byte("a"))
						if err != nil {
							fmt.Println("err7:", err)
							break
						}
					}
					_, err = seconn.Write([]byte(".hypixel.net"))
					if err != nil {
						fmt.Println("err7:", err)
						break
					}
					_, err = seconn.Write(buf[n1+4 : n])
					if err != nil {
						fmt.Println("err7:", err)
						break
					}
					fmt.Println(data)
					h = true
				}
			} else if strings.Index(data, "\x00") == 1 && strings.Index(data, "\x05") == 3 {
				if hwl != "false" {
					host := data[5 : 5+n1]
					fmt.Println(host)
					_, err := os.Stat("sips_data/" + host)
					if err != nil {
						seconn.Close()
						clconn.Close()
						return
					} else {
						bytes, err := ioutil.ReadFile("sips_data/" + host)
						if err != nil {
							fmt.Println(err)
							return
						}
						iptime, _ := strconv.Atoi(string(bytes[:10]))
						if iptime > (int)(time.Now().Unix()) {
							_, err = seconn.Write(buf[:5])
							if err != nil {
								fmt.Println("err7:", err)
								break
							}
							for i := 2; i < 2+n1-12; i++ {
								_, err = seconn.Write([]byte("a"))
								if err != nil {
									fmt.Println("err7:", err)
									break
								}
							}
							_, err = seconn.Write([]byte(".hypixel.net"))
							if err != nil {
								fmt.Println("err7:", err)
								break
							}
							_, err = seconn.Write(buf[n1+5 : n])
							if err != nil {
								fmt.Println("err7:", err)
								break
							}
							fmt.Println(data)
							h = true
						} else {
							seconn.Close()
							clconn.Close()
							return
						}
					}
				} else {
					_, err = seconn.Write(buf[:5])
					if err != nil {
						fmt.Println("err7:", err)
						break
					}
					for i := 2; i < 2+n1-12; i++ {
						_, err = seconn.Write([]byte("a"))
						if err != nil {
							fmt.Println("err7:", err)
							break
						}
					}
					_, err = seconn.Write([]byte(".hypixel.net"))
					if err != nil {
						fmt.Println("err7:", err)
						break
					}
					_, err = seconn.Write(buf[n1+5 : n])
					if err != nil {
						fmt.Println("err7:", err)
						break
					}
					fmt.Println(data)
					h = true
				}
			} else {
				d = true
			}
		} else {
			d = true
		}
		if d == true {
			_, err = seconn.Write(buf[:n])
			if err != nil {
				fmt.Println("err7:", err)
				break
			}
		}

	}
}
func sever(seconn net.Conn, clconn net.Conn) {
	defer seconn.Close()
	defer clconn.Close()
	for {
		reader := bufio.NewReader(seconn)
		var buf [16384]byte
		n, err := reader.Read(buf[:])
		if err != nil {
			fmt.Println("err7:", err)
			break
		}
		_, err = clconn.Write(buf[:n])
		if err != nil {
			fmt.Println("err7:", err)
			break
		}
	}
}

func api(apis string) {
	if apis != "false" {
		http.HandleFunc("/", handler)
		http.ListenAndServe(":"+apis, nil)
	}
}
func handler(w http.ResponseWriter, r *http.Request) {
	//获取所有请求参数
	query := r.URL.Query()
	_, err := json.Marshal(query)
	if err != nil {
		fmt.Println(err)
	}
	//获取指定请求参数
	host, ok := query["host"]
	if !ok || len(host[0]) < 1 {
		return
	}
	time, ok := query["time"]
	if !ok || len(time[0]) < 1 {
		return
	}
	txt, ok := query["txt"]
	if !ok || len(txt[0]) < 1 {
		return
	}
	if time[0] != "" && txt[0] != "" && host[0] != "" {
		n := true
		f, err := os.Create("sips_data/" + host[0])
		defer f.Close()
		if err != nil {
			// 创建文件失败处理
			n = false
		} else {
			content := time[0] + " " + txt[0]
			_, err = f.Write([]byte(content))
			if err != nil {
				// 写入失败处理
				n = false
			}
		}
		if n == false {
			fmt.Fprintf(w, "false")
		} else {
			fmt.Fprintf(w, "ture")
		}
	} else {
		fmt.Fprintf(w, "false")
	}

}
